/************************************
 文件明 ：  bsp_gpio.c
 作者   ：  胡秋峰
 描述   ：  GPIO操作文件
 日志   ：  修改pin参数类型为 uint32_t
            修改gpio_init()函数，支持中断配置
            添加中断相关函数
 ************************************/
#include "bsp_gpio.h"

/**
 * @描述            ： GPIO初始化函数
 * @参数 - base     ： GPIO组
 * @参数 - pin      ： GPIO组编号
 * @参数 - config   ： GPIO配置结构体
 * @返回值          ： 无 
 */
void gpio_init(GPIO_Type *base, uint32_t pin, gpio_pin_config_t *config)
{
    base->IMR &= ~(1U << pin);

    if (config->direction == kGPIO_DigitalInput) {
        base->GDIR &= ~(1 << pin);
    } else {
        base->GDIR |= (1 << pin);
        gpio_pin_write(base, pin, config->outputLogic);
    }
    gpio_int_config(base, pin, config->mode);
}

/**
 * @描述            ： 读取GPIO引脚电平
 * @参数 - base     ： GPIO组
 * @参数 - pin      ： GPIO组编号
 * @返回值          ： 引脚电平 0：低电平 1：高电平
 */
int gpio_pin_read(GPIO_Type *base, uint32_t pin)
{
    return ((base->DR >> pin) & 0x1);
}

/**
 * @描述            ： 指定GPIO引脚电平
 * @参数 - base     ： GPIO组
 * @参数 - pin      ： GPIO组编号
 * @参数 - value    ： 引脚电平 0：低电平 1：高电平
 * @返回值          ： 无
 */
void gpio_pin_write(GPIO_Type *base, uint32_t pin, int value)
{
    if (value == 0U) {
        base->DR &= ~(1U << pin);
    } else {
        base->DR |= (1U << pin);
    }
}

/**
 * @描述            ： 设置GPIO中断配置功能
 * @参数 - base     ： GPIO组
 * @参数 - pin      ： GPIO组编号
 * @参数 - mode     ： 中断模式
 * @返回值          ： 无
 */
void gpio_int_config(GPIO_Type *base, uint32_t pin, gpio_interrupt_mode_t mode)
{
    volatile uint32_t *icr;
    uint32_t icr_shift; /* icr_shift = pin%16 */

    icr_shift = pin;

    base->EDGE_SEL &= ~(1U << pin);

    if (pin < 16) { /* 低16位 */
        icr = &(base->ICR1);
    } else {
        icr = &(base->ICR2);
        icr_shift -= 16;
    }
    switch (mode)
    {
    case kGPIO_IntLowLevel:
        *icr &= ~(3U << (2 * icr_shift));
        break;
    case kGPIO_IntHightLevel:
        *icr = (*icr & (~(3U << (2 * icr_shift)))) | (1U << (2 * icr_shift));
        break;
    case kGPIO_IntRisingEdge:
        *icr = (*icr & (~(3U << (2 * icr_shift)))) | (2U << (2 * icr_shift));
        break;
    case kGPIO_IntFallingEdge:
        *icr |= (3U << (2 * icr_shift));
        break;
    case kGPIO_IntRisingOrFallingEdge:
        base->EDGE_SEL |= (1U << pin);
        break;
    default:
        break;
    }
}

/**
 * @描述            ： 使能GPIO中断功能
 * @参数 - base     ： GPIO组
 * @参数 - pin      ： GPIO组编号
 * @返回值          ： 无
 */
void gpio_int_enable(GPIO_Type *base, uint32_t pin)
{
    base->IMR |= (1U << pin);
}

/**
 * @描述            ： 禁止GPIO中断功能
 * @参数 - base     ： GPIO组
 * @参数 - pin      ： GPIO组编号
 * @返回值          ： 无
 */
void gpio_int_disable(GPIO_Type *base, uint32_t pin)
{
    base->IMR &= ~(1U << pin);
}

/**
 * @描述            ： 清除中断标志位
 * @参数 - base     ： GPIO组
 * @参数 - pin      ： GPIO组编号
 * @返回值          ： 无
 */
void gpio_clear_int_flags(GPIO_Type *base, uint32_t pin)
{
    base->ISR |= (1U << pin);
}
